/* Copyright (c) 2009, Michael Patraw
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * The name of Michael Patraw may not be used to endorse or promote
 *       products derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Michael Patraw ''AS IS'' AND ANY
 * ExPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Michael Patraw BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ExEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "at.h"

#include <assert.h>
#include <SDL/SDL.h>

/******************************************************************************\
 ATLIB Event Operations
\******************************************************************************/

/* Macros for converting from cell points to screen points and vise-versa.
 */
#define CELL_TO_SCREEN(x, y) {(x) *= AT_CHAR_WIDTH; (y) *= AT_CHAR_HEIGHT;}
#define SCREEN_TO_CELL(x, y) {(x) /= AT_CHAR_WIDTH; (y) /= AT_CHAR_HEIGHT;}

/* This variable is 1 when the user hasn't closed the window.
 */
int is_running = 1;

/* Static variable for storing events.
 */
static SDL_Event ev;

/* Current mouse state.
 */
static AtMouse mouse_state = {0, 0, 0, 0, 0, 0, 0, 0, 0};

static AtKey SDLEventToAtEvent(SDL_Event *ev)
{
    AtKey input;

    input.mod = SDL_GetModState();

    switch (ev->type) {
        /* KEYS */
        case SDL_KEYDOWN:
            input.key = ev->key.keysym.sym;
            break;
        /* MOUSE */
        case SDL_MOUSEMOTION:
            input.key = ATK_NONE;
            break;
        case SDL_MOUSEBUTTONDOWN:
            if (ev->button.button == 4)
                mouse_state.button |= ATM_WHEEL_UP;
            else if (ev->button.button == 5)
                mouse_state.button |= ATM_WHEEL_DOWN;
        case SDL_MOUSEBUTTONUP:
            input.key = ATK_NONE;
            break;
        /* QUITTING */
        case SDL_QUIT:
            is_running = 0;
            input.key = ATK_QUIT;
            break;
        default:
            input.key = ATK_NONE;
            break;
    }

    return input;
}

AtKey atGrabKey(void) {
    AtKey input;
    input.key = ATK_NONE;

    /* Flushes the event queue. */
    while (SDL_PollEvent(&ev))
        input = SDLEventToAtEvent(&ev);

    return input;
}

AtMouse atGrabMouse(void) {
    Uint8 status;

    mouse_state.button = 0;

    /* Flushes the event queue. */
    atGrabKey();

    SDL_PumpEvents();
    status = SDL_GetMouseState(&mouse_state.xabs, &mouse_state.yabs);
    SDL_GetRelativeMouseState(&mouse_state.relxabs, &mouse_state.relyabs);

    if (status & SDL_BUTTON(1)) {
        mouse_state.button |= ATM_LEFT;
    }
    if (status & SDL_BUTTON(2)) {
        mouse_state.button |= ATM_MIDDLE;
    }
    if (status & SDL_BUTTON(3)) {
        mouse_state.button |= ATM_RIGHT;
    }

    mouse_state.x = mouse_state.xabs;
    mouse_state.y = mouse_state.yabs;
    mouse_state.relx = mouse_state.relxabs;
    mouse_state.rely = mouse_state.relyabs;

    SCREEN_TO_CELL(mouse_state.x, mouse_state.y);
    SCREEN_TO_CELL(mouse_state.relx, mouse_state.rely);

    return mouse_state;
}

void atEnableRepeat(void) {
    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
}

void atDisableRepeat(void) {
    SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
}

/******************************************************************************\
 ATLIB Color
\******************************************************************************/

const AtColor ATC_STDBLACK = {0x00, 0x00, 0x00};
const AtColor ATC_STDBLUE = {0x00, 0x00, 0xFF};
const AtColor ATC_STDCYAN = {0x00, 0xFF, 0xFF};
const AtColor ATC_STDGREEN = {0x00, 0xFF, 0x00};
const AtColor ATC_STDMAGENTA = {0xFF, 0x00, 0xFF};
const AtColor ATC_STDRED = {0xFF, 0x00, 0x00};
const AtColor ATC_STDWHITE = {0xFF, 0xFF, 0xFF};
const AtColor ATC_STDYELLOW = {0xFF, 0xFF, 0x00};

const AtColor ATC_ALICEBLUE = {0xF0, 0xF8, 0xFF};
const AtColor ATC_ANTIQUEWHITE = {0xFA, 0xEB, 0xD7};
const AtColor ATC_AQUA = {0x00, 0xFF, 0xFF};
const AtColor ATC_AQUAMARINE = {0x7F, 0xFF, 0xD4};
const AtColor ATC_AZURE = {0xF0, 0xFF, 0xFF};
const AtColor ATC_BEIGE = {0xF5, 0xF5, 0xDC};
const AtColor ATC_BISQUE = {0xFF, 0xE4, 0xC4};
const AtColor ATC_BLACK = {0x00, 0x00, 0x00};
const AtColor ATC_BLANCHEDALMOND = {0xFF, 0xEB, 0xCD};
const AtColor ATC_BLUE = {0x00, 0x00, 0xFF};
const AtColor ATC_BLUEVIOLET = {0x8A, 0x2B, 0xE2};
const AtColor ATC_BROWN = {0xA5, 0x2A, 0x2A};
const AtColor ATC_BURLYWOOD = {0xDE, 0xB8, 0x87};
const AtColor ATC_CADETBLUE = {0x5F, 0x9E, 0xA0};
const AtColor ATC_CHARTREUSE = {0x7F, 0xFF, 0x00};
const AtColor ATC_CHOCOLATE = {0xD2, 0x69, 0x1E};
const AtColor ATC_CORAL = {0xFF, 0x7F, 0x50};
const AtColor ATC_CORNFLOWERBLUE = {0x64, 0x95, 0xED};
const AtColor ATC_CORNSILK = {0xFF, 0xF8, 0xDC};
const AtColor ATC_CRIMSON = {0xDC, 0x14, 0x3C};
const AtColor ATC_CYAN = {0x00, 0xFF, 0xFF};
const AtColor ATC_DARKBLUE = {0x00, 0x00, 0x8B};
const AtColor ATC_DARKCYAN = {0x00, 0x8B, 0x8B};
const AtColor ATC_DARKGOLDENROD = {0xB8, 0x86, 0x0B};
const AtColor ATC_DARKGRAY = {0xA9, 0xA9, 0xA9};
const AtColor ATC_DARKGREY = {0xA9, 0xA9, 0xA9};
const AtColor ATC_DARKGREEN = {0x00, 0x64, 0x00};
const AtColor ATC_DARKKHAKI = {0xBD, 0xB7, 0x6B};
const AtColor ATC_DARKMAGENTA = {0x8B, 0x00, 0x8B};
const AtColor ATC_DARKOLIVEGREEN = {0x55, 0x6B, 0x2F};
const AtColor ATC_DARKORANGE = {0xFF, 0x8C, 0x00};
const AtColor ATC_DARKORCHID = {0x99, 0x32, 0xCC};
const AtColor ATC_DARKRED = {0x8B, 0x00, 0x00};
const AtColor ATC_DARKSALMON = {0xE9, 0x96, 0x7A};
const AtColor ATC_DARKSEAGREEN = {0x8F, 0xBC, 0x8F};
const AtColor ATC_DARKSLATEBLUE = {0x48, 0x3D, 0x8B};
const AtColor ATC_DARKSLATEGRAY = {0x2F, 0x4F, 0x4F};
const AtColor ATC_DARKSLATEGREY = {0x2F, 0x4F, 0x4F};
const AtColor ATC_DARKTURQUOISE = {0x00, 0xCE, 0xD1};
const AtColor ATC_DARKVIOLET = {0x94, 0x00, 0xD3};
const AtColor ATC_DEEPPINK = {0xFF, 0x14, 0x93};
const AtColor ATC_DEEPSKYBLUE = {0x0, 0x0BF, 0xFF};
const AtColor ATC_DIMGRAY = {0x69, 0x69, 0x69};
const AtColor ATC_DIMGREY = {0x69, 0x69, 0x69};
const AtColor ATC_DODGERBLUE = {0x1E, 0x90, 0xFF};
const AtColor ATC_FIREBRICK = {0xB2, 0x22, 0x22};
const AtColor ATC_FLORALWHITE = {0xFF, 0xFA, 0xF0};
const AtColor ATC_FORESTGREEN = {0x22, 0x8B, 0x22};
const AtColor ATC_FUCHSIA = {0xFF, 0x00, 0xFF};
const AtColor ATC_GAINSBORO = {0xDC, 0xDC, 0xDC};
const AtColor ATC_GHOSTWHITE = {0xF8, 0xF8, 0xFF};
const AtColor ATC_GOLD = {0xFF, 0xD7, 0x00};
const AtColor ATC_GOLDENROD = {0xDA, 0xA5, 0x20};
const AtColor ATC_GRAY = {0x80, 0x80, 0x80};
const AtColor ATC_GREY = {0x80, 0x80, 0x80};
const AtColor ATC_GREEN = {0x00, 0x80, 0x00};
const AtColor ATC_GREENYELLOW = {0xAD, 0xFF, 0x2F};
const AtColor ATC_HONEYDEW = {0xF0, 0xFF, 0xF0};
const AtColor ATC_HOTPINK = {0xFF, 0x69, 0xB4};
const AtColor ATC_INDIANRED = {0xCD, 0x5C, 0x5C};
const AtColor ATC_INDIGO = {0x4B, 0x00, 0x82};
const AtColor ATC_IVORY = {0xFF, 0xFF, 0xF0};
const AtColor ATC_KHAKI = {0xF0, 0xE6, 0x8C};
const AtColor ATC_LAVENDER = {0xE6, 0xE6, 0xFA};
const AtColor ATC_LAVENDERBLUSH = {0xFF, 0xF0, 0xF5};
const AtColor ATC_LAWNGREEN = {0x7C, 0xFC, 0x00};
const AtColor ATC_LEMONCHIFFON = {0xFF, 0xFA, 0xCD};
const AtColor ATC_LIGHTBLUE = {0xAD, 0xD8, 0xE6};
const AtColor ATC_LIGHTCORAL = {0xF0, 0x80, 0x80};
const AtColor ATC_LIGHTCYAN = {0xE0, 0xFF, 0xFF};
const AtColor ATC_LIGHTGOLDENRODYELLOW = {0xFA, 0xFA, 0xD2};
const AtColor ATC_LIGHTGRAY = {0xD3, 0xD3, 0xD3};
const AtColor ATC_LIGHTGREY = {0xD3, 0xD3, 0xD3};
const AtColor ATC_LIGHTGREEN = {0x90, 0xEE, 0x90};
const AtColor ATC_LIGHTPINK = {0xFF, 0xB6, 0xC1};
const AtColor ATC_LIGHTSALMON = {0xFF, 0xA0, 0x7A};
const AtColor ATC_LIGHTSEAGREEN = {0x20, 0xB2, 0xAA};
const AtColor ATC_LIGHTSKYBLUE = {0x87, 0xCE, 0xFA};
const AtColor ATC_LIGHTSLATEGRAY = {0x77, 0x88, 0x99};
const AtColor ATC_LIGHTSLATEGREY = {0x77, 0x88, 0x99};
const AtColor ATC_LIGHTSTEELBLUE = {0xB0, 0xC4, 0xDE};
const AtColor ATC_LIGHTYELLOW = {0xFF, 0xFF, 0xE0};
const AtColor ATC_LIME = {0x00, 0xFF, 0x00};
const AtColor ATC_LIMEGREEN = {0x32, 0xCD, 0x32};
const AtColor ATC_LINEN = {0xFA, 0xF0, 0xE6};
const AtColor ATC_MAGENTA = {0xFF, 0x00, 0xFF};
const AtColor ATC_MAROON = {0x80, 0x00, 0x00};
const AtColor ATC_MEDIUMAQUAMARINE = {0x66, 0xCD, 0xAA};
const AtColor ATC_MEDIUMBLUE = {0x00, 0x00, 0xCD};
const AtColor ATC_MEDIUMORCHID = {0xBA, 0x55, 0xD3};
const AtColor ATC_MEDIUMPURPLE = {0x93, 0x70, 0xD8};
const AtColor ATC_MEDIUMSEAGREEN = {0x3C, 0xB3, 0x71};
const AtColor ATC_MEDIUMSLATEBLUE = {0x7B, 0x68, 0xEE};
const AtColor ATC_MEDIUMSPRINGGREEN = {0x00, 0xFA, 0x9A};
const AtColor ATC_MEDIUMTURQUOISE = {0x48, 0xD1, 0xCC};
const AtColor ATC_MEDIUMVIOLETRED = {0xC7, 0x15, 0x85};
const AtColor ATC_MIDNIGHTBLUE = {0x19, 0x19, 0x70};
const AtColor ATC_MINTCREAM = {0xF5, 0xFF, 0xFA};
const AtColor ATC_MISTYROSE = {0xFF, 0xE4, 0xE1};
const AtColor ATC_MOCCASIN = {0xFF, 0xE4, 0xB5};
const AtColor ATC_NAVAJOWHITE = {0xFF, 0xDE, 0xAD};
const AtColor ATC_NAVY = {0x00, 0x00, 0x80};
const AtColor ATC_OLDLACE = {0xFD, 0xF5, 0xE6};
const AtColor ATC_OLIVE = {0x80, 0x80, 0x00};
const AtColor ATC_OLIVEDRAB = {0x6B, 0x8E, 0x23};
const AtColor ATC_ORANGE = {0xFF, 0xA5, 0x00};
const AtColor ATC_ORANGERED = {0xFF, 0x45, 0x00};
const AtColor ATC_ORCHID = {0xDA, 0x70, 0xD6};
const AtColor ATC_PALEGOLDENROD = {0xEE, 0xE8, 0xAA};
const AtColor ATC_PALEGREEN = {0x98, 0xFB, 0x98};
const AtColor ATC_PALETURQUOISE = {0xAF, 0xEE, 0xEE};
const AtColor ATC_PALEVIOLETRED = {0xD8, 0x70, 0x93};
const AtColor ATC_PAPAYAWHIP = {0xFF, 0xEF, 0xD5};
const AtColor ATC_PEACHPUFF = {0xFF, 0xDA, 0xB9};
const AtColor ATC_PERU = {0xCD, 0x85, 0x3F};
const AtColor ATC_PINK = {0xFF, 0xC0, 0xCB};
const AtColor ATC_PLUM = {0xDD, 0xA0, 0xDD};
const AtColor ATC_POWDERBLUE = {0xB0, 0xE0, 0xE6};
const AtColor ATC_PURPLE = {0x80, 0x00, 0x80};
const AtColor ATC_RED = {0xFF, 0x00, 0x00};
const AtColor ATC_ROSYBROWN = {0xBC, 0x8F, 0x8F};
const AtColor ATC_ROYALBLUE = {0x41, 0x69, 0xE1};
const AtColor ATC_SADDLEBROWN = {0x8B, 0x45, 0x13};
const AtColor ATC_SALMON = {0xFA, 0x80, 0x72};
const AtColor ATC_SANDYBROWN = {0xF4, 0xA4, 0x60};
const AtColor ATC_SEAGREEN = {0x2E, 0x8B, 0x57};
const AtColor ATC_SEASHELL = {0xFF, 0xF5, 0xEE};
const AtColor ATC_SIENNA = {0xA0, 0x52, 0x2D};
const AtColor ATC_SILVER = {0xC0, 0xC0, 0xC0};
const AtColor ATC_SKYBLUE = {0x87, 0xCE, 0xEB};
const AtColor ATC_SLATEBLUE = {0x6A, 0x5A, 0xCD};
const AtColor ATC_SLATEGRAY = {0x70, 0x80, 0x90};
const AtColor ATC_SLATEGREY = {0x70, 0x80, 0x90};
const AtColor ATC_SNOW = {0xFF, 0xFA, 0xFA};
const AtColor ATC_SPRINGGREEN = {0x00, 0xFF, 0x7F};
const AtColor ATC_STEELBLUE = {0x46, 0x82, 0xB4};
const AtColor ATC_TAN = {0xD2, 0xB4, 0x8C};
const AtColor ATC_TEAL = {0x00, 0x80, 0x80};
const AtColor ATC_THISTLE = {0xD8, 0xBF, 0xD8};
const AtColor ATC_TOMATO = {0xFF, 0x63, 0x47};
const AtColor ATC_TURQUOISE = {0x40, 0xE0, 0xD0};
const AtColor ATC_VIOLET = {0xEE, 0x82, 0xEE};
const AtColor ATC_WHEAT = {0xF5, 0xDE, 0xB3};
const AtColor ATC_WHITE = {0xFF, 0xFF, 0xFF};
const AtColor ATC_WHITESMOKE = {0xF5, 0xF5, 0xF5};
const AtColor ATC_YELLOW = {0xFF, 0xFF, 0x00};
const AtColor ATC_YELLOWGREEN = {0x9A, 0xCD, 0x32};

/* Returns the SDL integer representation of an AtColor structure.
 */
#define ATCOLOR_TO_SDL(c) \
SDL_MapRGB(SDL_GetVideoSurface()->format, (c).r, (c).g, (c).b)

/******************************************************************************\
 ATLIB Font/Char Operations
\******************************************************************************/

/* Used for easily filling unused spots. */
#define reserved {{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0},\
{0,0,0,0,0,0}}

/* The internal font, 1 is foreground and 0 is background.
 */
char atfont[AT_CHAR_MAX][AT_CHAR_HEIGHT][AT_CHAR_WIDTH] =
{
    reserved, reserved, reserved, reserved, reserved,
    reserved, reserved, reserved, reserved, reserved,
    reserved, reserved, reserved, reserved, reserved,
    reserved, reserved, reserved, reserved, reserved,
    reserved, reserved, reserved, reserved, reserved,
    reserved, reserved, reserved, reserved, reserved,
    reserved, reserved, /* 0-31 */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 32 = ' ' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 33 = '!' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 34 = '"' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {1,1,1,1,1,0},
     {0,1,0,1,0,0},
     {1,1,1,1,1,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 35 = '#' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,1,0},
     {1,0,1,0,0,0},
     {1,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,1,0,1,0},
     {0,0,1,0,1,0},
     {1,1,1,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 36 = '$' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,0,0,1,0},
     {1,0,1,0,1,0},
     {0,1,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,1,0,0},
     {1,0,1,0,1,0},
     {1,0,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 37 = '%' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,0,0,0,0},
     {1,0,1,0,0,0},
     {1,0,1,0,0,0},
     {0,1,0,0,0,0},
     {1,0,1,0,0,0},
     {1,0,0,1,1,0},
     {1,0,0,1,0,0},
     {0,1,1,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 38 = '&' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 39 = ''' */
    {{0,0,0,0,0,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,0,0}}, /* 40 = '(' */
    {{0,0,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,0,0,0,0,0}}, /* 41 = ')' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {1,0,1,0,1,0},
     {0,1,1,1,0,0},
     {1,0,1,0,1,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 42 = '*' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {1,1,1,1,1,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 43 = '+' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,0,0,0,0,0}}, /* 44 = ',' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 45 = '-' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0}}, /* 46 = '.' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 47 = '/' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 48 = '0' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,0,0,0},
     {1,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 49 = '1' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 50 = '2' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 51 = '3' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,1,1,0,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {1,0,0,1,0,0},
     {1,1,1,1,1,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 52 = '4' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,1,1,0,0},
     {1,1,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 53 = '5' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 54 = '6' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 55 = '7' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 56 = '8' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,1,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 57 = '9' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0}}, /* 58 = ':' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,0,0,0,0,0}}, /* 59 = ';' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {1,0,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 60 = '<' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 61 = '=' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {1,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 62 = '>' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 63 = '?' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,1,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,1,0,0},
     {1,0,0,0,0,0},
     {0,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 64 = '@' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,1,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 65 = 'A' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,0,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,1,1,0,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {1,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 66 = 'B' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 67 = 'C' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,0,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {0,1,0,0,1,0},
     {1,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 68 = 'D' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 69 = 'E' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 70 = 'F' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 71 = 'G' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,1,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 72 = 'H' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 73 = 'I' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,1,1,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {1,0,0,1,0,0},
     {0,1,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 74 = 'J' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,1,0,0},
     {1,0,1,0,0,0},
     {1,1,0,0,0,0},
     {1,0,1,0,0,0},
     {1,0,0,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 75 = 'K' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 76 = 'L' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,0,1,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 77 = 'M' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,1,0,0,1,0},
     {1,1,0,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,0,1,1,0},
     {1,0,0,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 78 = 'N' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 79 = 'O' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,1,1,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 80 = 'P' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,1,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,0,0}}, /* 81 = 'Q' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,1,1,0,0},
     {1,0,1,0,0,0},
     {1,0,0,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 82 = 'R' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 83 = 'S' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 84 = 'T' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 85 = 'U' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 86 = 'V' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {0,1,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 87 = 'W' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 88 = 'X' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 89 = 'Y' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,1,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 90 = 'Z' */
    {{0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0}}, /* 91 = '[' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 92 = '\' */
    {{0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0}}, /* 94 = ']' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,1,0,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 95 = '^' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0}}, /* 96 = '_' */
    {{0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 97 = '`' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,1,0},
     {0,1,1,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,1,1,0},
     {0,1,1,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 98 = 'a' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 99 = 'b' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 100 = 'c' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,1,1,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 101 = 'd' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,1,1,1,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 102 = 'e' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,1,0,0},
     {0,1,0,0,1,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {1,1,1,1,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 103 = 'f' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,1,0},
     {0,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0}}, /* 104 = 'g' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,1,1,0,0},
     {1,1,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 105 = 'h' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 106 = 'i' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,1,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {0,0,0,1,0,0},
     {1,0,0,1,0,0},
     {1,0,0,1,0,0},
     {0,1,1,0,0,0}}, /* 107 = 'j' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,1,0,0},
     {1,0,1,0,0,0},
     {1,1,0,0,0,0},
     {1,0,1,0,0,0},
     {1,0,0,1,0,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 108 = 'k' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 109 = 'l' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,0,1,0,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 110 = 'm' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,1,1,0,0},
     {1,1,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 111 = 'n' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 112 = 'o' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,1,1,1,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0}}, /* 113 = 'p' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,1,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0},
     {0,0,0,0,1,0}}, /* 114 = 'q' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,1,1,0,0},
     {1,1,0,0,1,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {1,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 115 = 'r' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,1,1,0,0},
     {1,0,0,0,1,0},
     {0,1,1,0,0,0},
     {0,0,0,1,0,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 116 = 's' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {1,1,1,1,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,0,0},
     {0,1,0,0,1,0},
     {0,0,1,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 117 = 't' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,1,1,0},
     {0,1,1,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 118 = 'u' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,0,1,0,0},
     {0,1,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 119 = 'v' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {1,0,1,0,1,0},
     {0,1,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 120 = 'w' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {0,1,0,1,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,1,0,1,0,0},
     {1,0,0,0,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 121 = 'x' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,0,1,0},
     {1,0,0,1,1,0},
     {0,1,1,0,1,0},
     {0,0,0,0,1,0},
     {1,0,0,0,1,0},
     {0,1,1,1,0,0}}, /* 122 = 'y' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,1,0,0},
     {0,0,1,0,0,0},
     {0,1,0,0,0,0},
     {1,0,0,0,0,0},
     {1,1,1,1,1,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 123 = 'z' */
    {{0,0,0,0,0,0},
     {0,0,0,1,1,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {1,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,1,0},
     {0,0,0,0,0,0}}, /* 124 = '{' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 125 = '|' */
    {{0,0,0,0,0,0},
     {1,1,0,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,0,1,1,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {0,0,1,0,0,0},
     {1,1,0,0,0,0},
     {0,0,0,0,0,0}}, /* 126 = '}' */
    {{0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,1,0,0,1,0},
     {1,0,1,0,1,0},
     {1,0,0,1,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0},
     {0,0,0,0,0,0}}, /* 127 = '~' */
    reserved, reserved, reserved, reserved, reserved, /* 128-132 */
    reserved, reserved, reserved, reserved, reserved, /* 133-137 */
    reserved, reserved, reserved, reserved, reserved, /* 138-142 */
    reserved, reserved, reserved, reserved, reserved, /* 143-147 */
    reserved, reserved, reserved, reserved, reserved, /* 148-152 */
    reserved, reserved, reserved, reserved, reserved, /* 153-157 */
    reserved, reserved, reserved, reserved, reserved, /* 158-162 */
    reserved, reserved, reserved, reserved, reserved, /* 163-167 */
    reserved, reserved, reserved, reserved, reserved, /* 168-172 */
    reserved, reserved, reserved, reserved, reserved, /* 173-177 */
    reserved, reserved, reserved, reserved, reserved, /* 178-182 */
    reserved, reserved, reserved, reserved, reserved, /* 183-187 */
    reserved, reserved, reserved, reserved, reserved, /* 188-192 */
    reserved, reserved, reserved, reserved, reserved, /* 193-197 */
    reserved, reserved, reserved, reserved, reserved, /* 198-202 */
    reserved, reserved, reserved, reserved, reserved, /* 203-207 */
    reserved, reserved, reserved, reserved, reserved, /* 208-212 */
    reserved, reserved, reserved, reserved, reserved, /* 213-217 */
    reserved, reserved, reserved, reserved, reserved, /* 218-222 */
    reserved, reserved, reserved, reserved, reserved, /* 223-227 */
    reserved, reserved, reserved, reserved, reserved, /* 228-232 */
    reserved, reserved, reserved, reserved, reserved, /* 233-237 */
    reserved, reserved, reserved, reserved, reserved, /* 238-242 */
    reserved, reserved, reserved, reserved, reserved, /* 243-247 */
    reserved, reserved, reserved, reserved, reserved, /* 248-252 */
    reserved, reserved, reserved, reserved            /* 253-256 */
};

int atCharIsDefined(int c) {
    /* Checks if any other locatation except ' ' is blank, if it is
     * then it's not defined.
     */
    int fx, fy;

    if (c == ' ')
        return 1; /* Space is defined. */

    /* Check if it's location is reserved. */
    if (c >= 0 && c < 256)
        return 1;

    for (fy = 0; fy < AT_CHAR_HEIGHT; ++fy) {
        for (fx = 0; fx < AT_CHAR_WIDTH; ++fx) {
            if (atfont[c][fy][fx] != 0)
                return 1;
        }
    }

    return 0;
}

int atCharSet(int c, char rep[AT_CHAR_HEIGHT][AT_CHAR_WIDTH]) {
    int x, y;

    if (c < 0 || c >= AT_CHAR_MAX)
        return 0;

    /* Check if it's location is reserved. */
    if (c >= 0 && c < 256)
        return 0;

    for (y = 0; y < AT_CHAR_HEIGHT; ++y)
        for (x = 0; x < AT_CHAR_WIDTH; ++x)
            atfont[c][y][x] = rep[y][x];

    return 1;
}

/******************************************************************************\
 ATLIB Window Operations
\******************************************************************************/

/* Macros for getting/setting pixels, only works with 32-bit.
 */
#define GET_PIXEL(s, x, y) ((Uint32 *)(s)->pixels)[(y) * (s)->w + (x)]
#define SET_PIXEL(s, x, y, c) ((Uint32 *)(s)->pixels)[(y) * (s)->w + (x)] = (c)

/* Implement the window structure.
 */
struct AtWindow {
    SDL_Surface * surface;
    AtColor bgcolor;
};

AtWindow * atWindowCreate(int width, int height) {
    AtWindow * win;

    win = (AtWindow *)malloc(sizeof(AtWindow));

    if (win) {
        win->bgcolor = ATC_STDBLACK;

        /* Convert dimensions. */
        CELL_TO_SCREEN(width, height);


        win->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
                32, 0, 0, 0, 0);

        if (!win->surface) {
            atWindowDestroy(win);
            return NULL;
        }
    }

    return win;
}

AtWindow * atWindowLoadBmp(const char * filename) {
    AtWindow * win;

    win = (AtWindow *)malloc(sizeof(AtWindow));

    if (win) {
        win->bgcolor = ATC_STDBLACK;
        win->surface = NULL;

        SDL_Surface * temp = SDL_LoadBMP(filename);

        if (temp) {
            win->surface = SDL_DisplayFormat(temp);
            SDL_FreeSurface(temp);
        }

        if (!win->surface) {
            atWindowDestroy(win);
            return NULL;
        }
    }

    return win;
}

void atWindowDestroy(AtWindow * win) {
    if (win) {
        SDL_FreeSurface(win->surface);
        free(win);
    }
}

int atWindowWidth(AtWindow * win) {
    int w;
    int dummy; /* Dummy variable. */

    assert(win != NULL && win->surface != NULL);

    w = win->surface->w;

    SCREEN_TO_CELL(w, dummy);

    return w;
}

int atWindowHeight(AtWindow * win) {
    int h;
    int dummy; /* Dummy variable. */

    assert(win != NULL && win->surface != NULL);

    h = win->surface->h;

    SCREEN_TO_CELL(dummy, h);

    return h;
}

int atWindowWidthAbs(AtWindow * win) {
    assert(win != NULL && win->surface != NULL);

    return win->surface->w;
}

int atWindowHeightAbs(AtWindow * win) {
    assert(win != NULL && win->surface != NULL);

    return win->surface->h;
}

AtColor atWindowGetBgColor(AtWindow * win) {
    assert(win != NULL);

    return win->bgcolor;
}

void atWindowSetBgColor(AtWindow * win, AtColor col) {
    assert(win != NULL);

    win->bgcolor = col;

    atWindowClear(win);
}

void atWindowDrawPixel(AtWindow * win, int x, int y, AtColor col) {
    assert(win != NULL && win->surface != NULL);

    if (x >= 0 && x < win->surface->w && y >= 0 && y < win->surface->h)
        SET_PIXEL(win->surface, x, y, ATCOLOR_TO_SDL(col));
}

void atWindowDrawChar(AtWindow * win, int x, int y, AtColor fg, AtColor bg,
        int c) {
    int fx, fy;

    assert(c >= 0 && c < AT_CHAR_MAX);
    assert(win != NULL && win->surface != NULL);

    CELL_TO_SCREEN(x, y);

    for (fy = 0; fy < AT_CHAR_HEIGHT; ++fy) {
        for (fx = 0; fx < AT_CHAR_WIDTH; ++fx) {
            if (x + fx >= 0 && x + fx < atWindowWidthAbs(win) &&
                y + fy >= 0 && y + fy < atWindowHeightAbs(win)) {
                if (atfont[c][fy][fx])
                    SET_PIXEL(win->surface, fx + x, fy + y, ATCOLOR_TO_SDL(fg));
                else
                    SET_PIXEL(win->surface, fx + x, fy + y, ATCOLOR_TO_SDL(bg));
            }
        }
    }
}

void atWindowDrawCharAbs(AtWindow * win, int x, int y, AtColor fg, AtColor bg,
        int c) {
    int fx, fy;

    assert(c >= 0 && c < AT_CHAR_MAX);
    assert(win != NULL && win->surface != NULL);

    for (fy = 0; fy < AT_CHAR_HEIGHT; ++fy) {
        for (fx = 0; fx < AT_CHAR_WIDTH; ++fx) {
            if (x + fx >= 0 && x + fx < atWindowWidthAbs(win) &&
                y + fy >= 0 && y + fy < atWindowHeightAbs(win)) {
                if (atfont[c][fy][fx])
                    SET_PIXEL(win->surface, fx + x, fy + y, ATCOLOR_TO_SDL(fg));
                else
                    SET_PIXEL(win->surface, fx + x, fy + y, ATCOLOR_TO_SDL(bg));
            }
        }
    }
}

void atWindowDrawString(AtWindow * win, int x, int y, AtColor fg, AtColor bg,
        const char * str) {
    unsigned long len, i;

    len = strlen(str);

    for (i = 0; i < len; ++i) {
        if (str[i] == '\n') {
            x = 0;
            ++y;
        }
        else if (str[i] == '\t') {
            x += 4;
        }
        else {
            atWindowDrawChar(win, x, y, fg, bg, str[i]);
            ++x;
        }
    }
}

void atWindowDrawStringAbs(AtWindow * win, int x, int y, AtColor fg, AtColor bg,
        const char * str) {
    unsigned long len, i;

    len = strlen(str);

    for (i = 0; i < len; ++i) {
        if (str[i] == '\n') {
            x = 0;
            y += AT_CHAR_HEIGHT;
        }
        else if (str[i] == '\t') {
            x += 4 * AT_CHAR_WIDTH;
        }
        else {
            atWindowDrawCharAbs(win, x, y, fg, bg, str[i]);
            x += AT_CHAR_WIDTH;
        }
    }
}

void atWindowDrawStringWrap(AtWindow * win, int x, int y,
        AtColor fg, AtColor bg, const char * str) {
    int wordlen, width;

    assert(win != NULL);

    width = (int)atWindowWidth(win);

    for (; *str != '\0'; ++str) {
        /* Try wrapping. */
        wordlen = (int)strcspn(str + 1, " ");
        if (x + wordlen >= width) {
            if (wordlen >= width) {
                /* Too long, just print it. */
                width = 0;
                width = ~width;
            }
            else {
                x = 0;
                ++y;
                if (*str == ' ')
                    ++str;
            }
        }

        if (*str == '\n') {
            x = 0;
            ++y;
        }
        else if (*str == '\t') {
            x += 4;
        }
        else {
            atWindowDrawChar(win, x, y, fg, bg, *str);
            ++x;
        }

        if (*(str + 1) == ' ' && x + 1 >= atWindowWidth(win)) {
            x = 0;
            ++y;
            ++str;
        }
    }
}

void atWindowDrawStringWrapAbs(AtWindow * win, int x, int y,
        AtColor fg, AtColor bg, const char * str) {
    int wordlen, width;

    assert(win != NULL);

    width = (int)atWindowWidthAbs(win);

    for (; *str != '\0'; ++str) {
        /* Try wrapping. */
        wordlen = (int)strcspn(str + 1, " ");
        if (x + wordlen * AT_CHAR_WIDTH >= width) {
            if (wordlen * AT_CHAR_WIDTH >= width) {
                /* Too long, just print it. */
                width = 0;
                width = ~width;
            }
            else {
                x = 0;
                y += AT_CHAR_HEIGHT;
                if (*str == ' ')
                    ++str;
            }
        }

        if (*str == '\n') {
            x = 0;
            y += AT_CHAR_HEIGHT;
        }
        else if (*str == '\t') {
            x += 4 * AT_CHAR_WIDTH;
        }
        else {
            atWindowDrawCharAbs(win, x, y, fg, bg, *str);
            x += AT_CHAR_WIDTH;
        }

        if (*(str + 1) == ' ' && x + 1 >= atWindowWidthAbs(win)) {
            x = 0;
            y += AT_CHAR_HEIGHT;
            ++str;
        }
    }
}

void atWindowSetColorKey(AtWindow * win, AtColor color) {
    assert(win != NULL && win->surface != NULL);

    Uint32 colorkey = SDL_MapRGB(win->surface->format,
            color.r, color.g, color.b);

    SDL_SetColorKey(win->surface, SDL_SRCCOLORKEY, colorkey);
}

void atWindowSetAlpha(AtWindow * win, unsigned char val) {
    assert(win != NULL && win->surface != NULL);

    SDL_SetAlpha(win->surface, SDL_SRCALPHA, val);
}

void atWindowBlit(AtWindow * dst, int x, int y, AtWindow * src,
        int sx, int sy, int sw, int sh) {
    SDL_Rect loc;
    SDL_Rect src_area;

    assert(dst != NULL && dst->surface != NULL);
    assert(src != NULL && src->surface != NULL);

    CELL_TO_SCREEN(x, y);
    CELL_TO_SCREEN(sx, sy);

    /* Set sw and sh to max if they were -1.
       As sw or sh become lower the size is reduced from the max,
       like -1 is height, -2 is height - 1, -3 is height - 2. */
    if (sw <= -1)
        sw = atWindowWidth(src) - sx + (sw + 1);
    if (sh <= -1)
        sh = atWindowHeight(src) - sy + (sh + 1);
    CELL_TO_SCREEN(sw, sh);

    loc.x = x;
    loc.y = y;

    src_area.x = sx;
    src_area.y = sy;
    src_area.w = sw;
    src_area.h = sh;

    SDL_BlitSurface(src->surface, &src_area, dst->surface, &loc);
}

void atWindowBlitAbs(AtWindow * dst, int x, int y, AtWindow * src,
        int sx, int sy, int sw, int sh) {
    SDL_Rect loc;
    SDL_Rect src_area;

    assert(dst != NULL && dst->surface != NULL);
    assert(src != NULL && src->surface != NULL);

    /* Set sw and sh to max if they were -1.
       As sw or sh become lower the size is reduced from the max,
       like -1 is height, -2 is height - 1, -3 is height - 2. */
    if (sw <= -1)
        sw = atWindowWidthAbs(src) - sx + (sw + 1);
    if (sh <= -1)
        sh = atWindowHeightAbs(src) - sy + (sh + 1);

    loc.x = x;
    loc.y = y;

    src_area.x = sx;
    src_area.y = sy;
    src_area.w = sw;
    src_area.h = sh;

    SDL_BlitSurface(src->surface, &src_area, dst->surface, &loc);
}

void atWindowClear(AtWindow * win) {
    assert(win != NULL && win->surface != NULL);

    SDL_FillRect(win->surface, NULL, ATCOLOR_TO_SDL(win->bgcolor));
}

/******************************************************************************\
 ATLIB Core Operations
\******************************************************************************/

/* Keep the pointer to the main surface with the background.
 */
static AtWindow * stdwin = NULL;

int atStart(const char * title, int width, int height) {
    unsigned long flags = SDL_SWSURFACE | SDL_DOUBLEBUF;

    if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
        return 0;

    CELL_TO_SCREEN(width, height);

    stdwin = (AtWindow *)malloc(sizeof(AtWindow));
    if (stdwin == NULL)
        return 0;

    stdwin->surface = SDL_SetVideoMode(width, height, 32, flags);
    stdwin->bgcolor = ATC_STDBLACK;

    if (stdwin == NULL)
        return 0;

    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

    SDL_WM_SetCaption(title, NULL);

    return 1;
}

void atStop(void) {
    if (stdwin)
        free(stdwin);
    SDL_Quit();
}

int atIsRunning(void) {
    return is_running;
}

void atStopRunning(void) {
    is_running = 0;
}

unsigned long atGetMili(void) {
    return SDL_GetTicks();
}

void atDelay(unsigned long mili) {
    SDL_Delay(mili);
}

int atGetCursor(void) {
    if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE)
        return AT_CURSORVISIBLE;
    return AT_CURSORINVISIBLE;
}

void atSetCursor(int cur) {
    if (cur == AT_CURSORVISIBLE)
        SDL_ShowCursor(SDL_ENABLE);
    else
        SDL_ShowCursor(SDL_DISABLE);
}

void atToggleFullScreen(void) {
    assert(stdwin != NULL && stdwin->surface != NULL);
    SDL_WM_ToggleFullScreen(stdwin->surface);
}

void atSetTitle(const char * title) {
    SDL_WM_SetCaption(title, NULL);
}

const char * atGetTitle(void) {
    static char * title;
    SDL_WM_GetCaption(&title, NULL);
    return title;
}

int atWidth(void) {
    return atWindowWidth(stdwin);
}

int atHeight(void) {
    return atWindowHeight(stdwin);
}

int atWidthAbs(void) {
    return atWindowWidthAbs(stdwin);
}

int atHeightAbs(void) {
    return atWindowHeightAbs(stdwin);
}

AtColor atGetBgColor(void) {
    return atWindowGetBgColor(stdwin);
}

void atSetBgColor(AtColor col) {
    atWindowSetBgColor(stdwin, col);
}

void atDrawPixel(int x, int y, AtColor col) {
    atWindowDrawPixel(stdwin, x, y, col);
}

void atDrawChar(int x, int y, AtColor fg, AtColor bg, int c) {
    atWindowDrawChar(stdwin, x, y, fg, bg, c);
}

void atDrawCharAbs(int x, int y, AtColor fg, AtColor bg, int c) {
    atWindowDrawCharAbs(stdwin, x, y, fg, bg, c);
}

void atDrawString(int x, int y, AtColor fg, AtColor bg, const char * str) {
    atWindowDrawString(stdwin, x, y, fg, bg, str);
}

void atDrawStringAbs(int x, int y, AtColor fg, AtColor bg, const char * str) {
    atWindowDrawStringAbs(stdwin, x, y, fg, bg, str);
}

void atDrawStringWrap(int x, int y, AtColor fg, AtColor bg,
        const char * str) {
    atWindowDrawStringWrap(stdwin, x, y, fg, bg, str);
}

void atDrawStringWrapAbs(int x, int y, AtColor fg, AtColor bg,
        const char * str) {
    atWindowDrawStringWrapAbs(stdwin, x, y, fg, bg, str);
}

void atBlit(int x, int y, AtWindow * src, int sx, int sy, int sw, int sh) {
    atWindowBlit(stdwin, x, y, src, sx, sy, sw, sh);
}

void atBlitAbs(int x, int y, AtWindow * src, int sx, int sy, int sw, int sh) {
    atWindowBlitAbs(stdwin, x, y, src, sx, sy, sw, sh);
}

void atClear(void) {
    atWindowClear(stdwin);
}

void atUpdate(void) {
    assert(stdwin != NULL);

    SDL_Flip(stdwin->surface);
}

